import {
  WebGLRenderer,
  Scene,
  MOUSE,
  RepeatWrapping,
  Color,
  PerspectiveCamera,
  Vector3,
  Raycaster,
  Vector2
} from 'three'
import Status from 'three/examples/jsm/libs/stats.module'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { TransformControls } from 'three/examples/jsm/controls/TransformControls'
// import { DragControls } from 'three/examples/jsm/controls/DragControls.js'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js'
import { triPattern } from '@/components/Three/JS/Loadphoto.js'

import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
import { spotLight } from '@/components/Three/JS/Light.js'
export class TEngine {
  constructor(dom) {
    this.exportModel = ''

    this.renderer = new WebGLRenderer({ antialias: true })
    this.scene = new Scene()
    this.camera = new PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 100000)

    this.scene.add(this.camera)
    this.renderer.clearColor()
    this.scene.background = new Color(0xbfe3dd)
    this.camera.position.set(0, 36, 11) //设置相机位置
    this.camera.lookAt(new Vector3(0, 0, 0)) //设置相机方向
    this.camera.up = new Vector3(0, 1, 0) //设置相机的抬头
    // this.camera.aspect = 1.7 //设置相机的抬头

    this.renderer.setPixelRatio(window.devicePixelRatio)
    // this.renderer.setSize(dom.offsetWidth, dom.offsetHeight, true)
    this.renderer.setSize(window.innerWidth, window.innerHeight, true)
    this.renderer.setPixelRatio(window.devicePixelRatio) //为了兼容高清屏幕
    dom.appendChild(this.renderer.domElement)

    // 初始性能监视器(Status是用方法写的,不是对象,所有不用new)
    const stats = new Status()
    const statsDom = stats.domElement
    statsDom.style.position = 'fixed'
    statsDom.style.top = '40px'
    statsDom.style.left = '10px'
    dom.appendChild(statsDom)

    // 初始orbitControls让相机跟着鼠标观察
    const orbitControls = new OrbitControls(this.camera, this.renderer.domElement)
    this.orbitControls = orbitControls
    orbitControls.enableDamping = true
    orbitControls.target = new Vector3(0, 0, 0)

    //初始变换控制器
    const mouse = new Vector2()
    //初始射线拾取器
    const raycaster = new Raycaster()

    // 初始化变换控制器
    let time = ''
    let lock = true
    let raycasterModel = ''
    let selectedObjects = []

    this.transformControls = new TransformControls(this.camera, this.renderer.domElement)
    this.scene.remove(this.transformControls) //移除变换控制器，因为加入变换控制器添加到了scene.children的0号位置
    this.scene.add(this.transformControls) //移除后需要重新添加变换控制器
    // let transflag = false
    //  this.transformControls.addEventListener('mouseDown', () => {
    //   transflag = true
    // })
    //  this.transformControls.addEventListener('mouseUp', () => {
    //   transflag = true
    // })
    this.renderer.domElement.addEventListener('pointermove', (event) => {
      // console.log(event.offsetX, event.offsetY)
      if (event.isPrimary === false) return

      var domx = event.clientX
      var domy = event.clientY
      var width = this.renderer.domElement.offsetWidth
      var height = this.renderer.domElement.offsetHeight
      mouse.x = (domx / width) * 2 - 1
      mouse.y = -(2 * domy) / height + 1
      // console.log(mouse.x, mouse.y)
      raycaster.setFromCamera(mouse, this.camera) //告诉拾取器，从哪个相机去获取点
      let exportmod = raycaster.intersectObjects(this.scene.children, true)
      if (exportmod.length > 0) {
        this.exportModel = exportmod[0].object
        const selectedObject = exportmod[0].object
        addSelectedObject(selectedObject)
        outlinePass.selectedObjects = selectedObjects
      } else {
        outlinePass.selectedObjects = []
      }
      // console.log(selectedObjects, '鼠标下得模型')
      // checkIntersection()
      // scene.remove( this.transformControls) //移除变换控制器，因为加入变换控制器添加到了scene.children的0号位置
      // scene.add( this.transformControls) //移除后需要重新添加变换控制器
    })
    // 开始测试outline
    let composer = new EffectComposer(this.renderer)
    composer.setSize(this.renderer.domElement.offsetWidth, this.renderer.domElement.offsetHeight)

    this.composer = composer
    const renderPass = new RenderPass(this.scene, this.camera)
    composer.addPass(renderPass)

    let outlinePass = new OutlinePass(new Vector2(window.innerWidth, window.innerHeight), this.scene, this.camera)
    outlinePass.hiddenEdgeColor.set(0x0ff40b)
    outlinePass.visibleEdgeColor.set(0xf20d0d)
    outlinePass.usePatternTexture = true
    triPattern.wrapS = RepeatWrapping
    triPattern.wrapT = RepeatWrapping
    outlinePass.patternTexture = triPattern
    outlinePass.edgeStrength = Number(6)
    composer.addPass(outlinePass)

    const addSelectedObject = (object) => {
      selectedObjects = []
      selectedObjects.push(object)
    }

    // 结束测试outline
    const animate = () => {
      this.renderer.render(this.scene, this.camera)
      animate && requestAnimationFrame(animate)
      stats.update()
      // 通过摄像机和鼠标位置更新射线
      raycaster.setFromCamera(mouse, this.camera)
      // this.transformControls.update()
      composer.render()
      orbitControls.update()
    }
    animate()

    this.renderer.domElement.addEventListener('click', async () => {
      this.transformControls.detach()
      orbitControls.mouseButtons = {
        LEFT: MOUSE.ROTATE,
        MIDDLE: MOUSE.DOLLY,
        RIGHT: MOUSE.PAN
      }
      if (!lock) {
        console.log(111111)
      }
      this.render()
    })
    window.addEventListener('resize', this.onWindwResize.bind(this))

    this.renderer.domElement.addEventListener('dblclick', async () => {
      orbitControls.mouseButtons = {
        LEFT: null,
        MIDDLE: MOUSE.DOLLY,
        RIGHT: MOUSE.PAN
      }
      // this.transformControls.size = 0.5
      raycaster.setFromCamera(mouse, this.camera) //告诉拾取器，从哪个相机去获取点
      const intersection = raycaster.intersectObjects(this.scene.children, true)
      if (intersection.length) {
        const object = intersection[0].object
        raycasterModel = object
        console.log(object, '双击选取的第一个模型')
      }
      this.transformControls.attach(raycasterModel)
    })
    // 区分鼠标长按和点击事件
    this.renderer.domElement.addEventListener('mousedown', () => {
      time = setTimeout(() => {
        console.log('长按事件')
        lock = false
      }, 500)
    })
    this.renderer.domElement.addEventListener('mouseup', () => {
      clearTimeout(time)
      setTimeout(() => {
        lock = true
      })
    })
    // this.renderer.domElement.addEventListener('pointermove', onPointerMove)
    this.selectedObjects = []

    this.BuildGui()
    // this.EffectOutline()
  }
  render() {
    this.renderer.render(this.scene, this.camera)
  }
  //创建GUI
  BuildGui() {
    let gui = new GUI()
    const params = {
      'light color': spotLight.color.getHex(),
      intensity: spotLight.intensity
    }
    gui.addColor(params, 'light color').onChange(function (val) {
      console.log('触发了颜色切换', val)
      spotLight.color.setHex(val)
    })
    gui.add(params, 'intensity', 0, 2).onChange(function (val) {
      spotLight.intensity = val
      // this.renderer && this.renderer.render(this.scene, this.camera)
    })
    gui.open()
  }
  //监听窗口变化，改变窗户
  onWindwResize() {
    this.camera.aspect = window.innerWidth / window.innerHeight
    this.camera.updateProjectionMatrix()
    this.renderer.setSize(window.innerWidth, window.innerHeight)
    this.renderer && this.renderer.render(this.scene, this.camera)
    this.composer.setSize(window.innerWidth, window.innerHeight)
  }
}
